//-------------------------------------------------------------------
//	Copyright (c) 2010-2012  Zhirnov Andrey
//	This file is part of the "UXGEN" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#ifndef _UX_BASE_OBJECT_H
#define _UX_BASE_OBJECT_H

#include "MainTypes.h"
#include "../GL/opengl.h"
#include "../CL/opencl.h"
#include "Events.h"

namespace Engine
{
	
	//
	// Thread Local Object
	//

	struct TThreadObject
	{
	private:
		THREAD_LOCAL static gl4Context			* _pGLContext;
		THREAD_LOCAL static CStateManager		* _SMAN;
		THREAD_LOCAL static IThread				* _THREAD;
		THREAD_LOCAL static CCore				* _CORE;
		THREAD_LOCAL static UX_OSAPI			* _OSAPI;
		THREAD_LOCAL static IWindow				* _WINDOW;
		THREAD_LOCAL static CLogger				* _LOGGER;
		THREAD_LOCAL static CRenderThread		* _RENDER;
		THREAD_LOCAL static CRenderGL			* _RENDERGL;
		THREAD_LOCAL static CRender				* _MAIN_RENDER;
		THREAD_LOCAL static CLDevice			* _CLDEVICE;
		THREAD_LOCAL static CInput				* _INPUT;
		THREAD_LOCAL static CFileSystem			* _FILESYS;
		THREAD_LOCAL static CGLObjectManager	* _GLOM;
		THREAD_LOCAL static CResourceManager	* _RESMAN;
		THREAD_LOCAL static CSoundSystem		* _SOUNDSYS;
		THREAD_LOCAL static CConfig				* _CONFIG;
		THREAD_LOCAL static CObjectManager		* _OBJMAN;
		THREAD_LOCAL static CGUISystem			* _GUISYS;
		THREAD_LOCAL static CGUIObjectFactory	* _GUIFACTORY;
		THREAD_LOCAL static CSceneObjectFactory	* _SOFACTORY;
		THREAD_LOCAL static CBatchRender		* _BATCH;
		THREAD_LOCAL static CMatrixStack		* _MSTACK;

	public:
		inline static Ptr< gl4Context >			GLContext()		{ return _pGLContext; }
		inline static Ptr< CStateManager >		SMAN()			{ return _SMAN; }
		inline static Ptr< IThread >			THREAD()		{ return _THREAD; }
		inline static Ptr< CCore >				CORE()			{ return _CORE; }
		inline static Ptr< UX_OSAPI >			OSAPI()			{ return _OSAPI; }
		inline static Ptr< IWindow >			WINDOW()		{ return _WINDOW; }
		inline static Ptr< CLogger >			LOGGER()		{ return _LOGGER; }
		inline static Ptr< CRenderThread >		RENDER()		{ return _RENDER; }
		inline static Ptr< CRenderGL >			RENDERGL()		{ return _RENDERGL; }
		inline static Ptr< CRender >			MAIN_RENDER()	{ return _MAIN_RENDER; }
		inline static Ptr< CLDevice >			CLDEVICE()		{ return _CLDEVICE; }
		inline static Ptr< CInput >				INPUT()			{ return _INPUT; }
		inline static Ptr< CFileSystem >		FILESYS()		{ return _FILESYS; }
		inline static Ptr< CGLObjectManager >	GLOM()			{ return _GLOM; }
		inline static Ptr< CResourceManager >	RESMAN()		{ return _RESMAN; }
		inline static Ptr< CSoundSystem >		SOUNDSYS()		{ return _SOUNDSYS; }
		inline static Ptr< CConfig >			CONFIG()		{ return _CONFIG; }
		inline static Ptr< CObjectManager >		OBJMAN()		{ return _OBJMAN; }
		inline static Ptr< CGUISystem >			GUISYS()		{ return _GUISYS; }
		inline static Ptr< CGUIObjectFactory >	GUIFACTORY()	{ return _GUIFACTORY; }
		inline static Ptr< CSceneObjectFactory>	SOFACTORY()		{ return _SOFACTORY; }
		inline static Ptr< CBatchRender >		BATCH()			{ return _BATCH; }
		inline static Ptr< CMatrixStack >		MSTACK()		{ return _MSTACK; }

		inline static void GLContext(gl4Context *pContext)		{ _pGLContext = pContext; }
		inline static void SMAN(CStateManager *pSM)				{ _SMAN  = pSM; }
		inline static void BATCH(CBatchRender *pBR)				{ _BATCH = pBR; }
		inline static void WINDOW(IWindow *pWnd)				{ _WINDOW = pWnd; }
		
	public:
		// call this function on enter thread only
		static void OnEnterThread(CCore *, IThread *);

		// call this function on exit thread only
		static void OnExitThread();
		
		static void	_s_SetSystems(CCore *, IWindow *, IThread *);
	};



	//
	// Engine Base Object
	//

	class _EXPORT_ CEngBaseObject
	{
	protected:
		inline static Ptr< CCore >				CORE()			{ return GLOBAL::CORE(); }
		inline static Ptr< UX_OSAPI >			OSAPI()			{ return GLOBAL::OSAPI(); }
		inline static Ptr< IWindow >			WINDOW()		{ return GLOBAL::WINDOW(); }
		inline static Ptr< CLogger >			LOGGER()		{ return GLOBAL::LOGGER(); }
		inline static Ptr< CRenderThread >		RENDER()		{ return GLOBAL::RENDER(); }
		inline static Ptr< CRenderGL >			RENDERGL()		{ return GLOBAL::RENDERGL(); }
		inline static Ptr< CRender >			MAIN_RENDER()	{ return GLOBAL::MAIN_RENDER(); }
		inline static Ptr< CLDevice >			CLDEVICE()		{ return GLOBAL::CLDEVICE(); }
		inline static Ptr< CInput >				INPUT()			{ return GLOBAL::INPUT(); }
		inline static Ptr< CFileSystem >		FILESYS()		{ return GLOBAL::FILESYS(); }
		inline static Ptr< CGLObjectManager >	GLOM()			{ return GLOBAL::GLOM(); }
		inline static Ptr< CResourceManager >	RESMAN()		{ return GLOBAL::RESMAN(); }
		inline static Ptr< CSoundSystem >		SOUNDSYS()		{ return GLOBAL::SOUNDSYS(); }
		inline static Ptr< CConfig >			CONFIG()		{ return GLOBAL::CONFIG(); }
		inline static Ptr< CObjectManager >		OBJMAN()		{ return GLOBAL::OBJMAN(); }
		inline static Ptr< CGUISystem >			GUISYS()		{ return GLOBAL::GUISYS(); }
		inline static Ptr< CGUIObjectFactory >	GUIFACTORY()	{ return GLOBAL::GUIFACTORY(); }
		inline static Ptr< CSceneObjectFactory>	SOFACTORY()		{ return GLOBAL::SOFACTORY(); }
		inline static Ptr< CBatchRender >		BATCH()			{ return GLOBAL::BATCH(); }
		inline static Ptr< CMatrixStack >		MSTACK()		{ return GLOBAL::MSTACK(); }
		inline static Ptr< CStateManager >		SMAN()			{ return GLOBAL::SMAN(); }
		inline static Ptr< IThread >			THREAD()		{ return GLOBAL::THREAD(); }

	public:
		CEngBaseObject() {}
		virtual ~CEngBaseObject() {}

		virtual void Release() = 0;
	};


	
	//
	// Core Event Listener
	//

	class _EXPORT_ ICoreEventListener : public CEngBaseObject,
										public IWindowEventListener,
										public IWindowUpdater
	{
	public:
		virtual void OnInit() = 0;
		virtual void OnFree() = 0;
		virtual void OnException() = 0;
		virtual e_win_event::type GetEvents() = 0;
	};



	//
	// User Thread Local Storage Callback
	//

	class IUserTLSCallback
	{
	public:
		virtual void OnEnterThread(IThread *) = 0;
		virtual void OnExitThread(IThread *) = 0;
	};



	//
	// API Errors Checker
	//
	
	struct _EXPORT_ TAPIErrorChecker
	{
		// max cicles count while clear errors
		static uint	uMaxErrors;

		// OpenGL //
		static void ClearGLErrors();
		static bool CheckGLError(const char *pGLFunc, const char *pFunc, const char *pFile, uint uLine);
		static bool CheckGLErrors(const char *pFile, uint uLine);

		// OpenCL //
		static bool CheckCLError(cl_int err, const char *pCLFunc, const char *pFunc, const char *pFile, uint uLine);

		// OpenAL //
		static void ClearALErrors();
		static void ClearALCErrors();
		static bool CheckALError(const char *pALFunc, const char *pFunc, const char *pFile, uint uLine);
		static bool CheckALCError(const char *pALCFunc, const char *pFunc, const char *pFile, uint uLine);
		static bool CheckALErrors(const char *pFile, uint uLine);
		static bool CheckALCErrors(const char *pFile, uint uLine);

		// OS //
		static void ClearOSErrors();
		static bool CheckOSError(const char *pOSFunc, const char *pFunc, const char *pFile, uint uLine);
		static bool CheckOSErrors(const char *pFile, uint uLine);
	};
	
//-------------------------------------------------------------------

}	// Engine

#endif	// _UX_BASE_OBJECT_H